import json
import random
from datetime import timedelta, datetime, date

import asyncio

import aiohttp
import aioredis
import motor
import tornado.web
import tornado.ioloop
from faker import Faker
from tornado import gen
from baseHandler import PayHandler, init_logger
# from cmcc import get_ts
import time
import base64
import lxml.html

# from util.cmcc_ft import cmcc_query
from util.unicom_10010 import get_unicom_ali
from util.cmcc_10086 import cmcc_10086_query
from util.ctcc2 import ctcc_query

logger = init_logger("cmcc", "/app/log/cs_cmcc/tongji2.log")


def get_ts():
    return str(time.time()).replace('.', '')[:13]

async def cmcc_query(query_url, redis):

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
    }
    proxys = await redis.smembers('un_proxy', encoding='utf-8')
    proxy = random.choice(list(proxys))
    logger.info(proxy)
    if proxy:
        conn = proxy
    else:
        conn = None
    # conn = None

    async with aiohttp.ClientSession(headers=headers) as session:
        url = "https://dev.10086.cn/api/accessURL?sspId=63861&pageId=P170808008"
        async with session.get(url, proxy=conn) as rsp:
            text = await rsp.text()


            # return orderstate,  message
        orderid = query_url.split('/')[-1]
        url = 'https://open.10086.cn/h5/payorder/status?orderId=%s' % orderid
        async with session.get(url, proxy=conn) as rsp:
            res = await rsp.json()
            # 02 2
            print(res)
            if res['data']['payStatus'] == "1":  # 01
                orderstate = "0"
            elif res['data']['payStatus'] == "3":  # "00"
                orderstate = '8'
            # elif res['data']['payStatus'] == "20":
            #     orderstate = '1'
            else:
                orderstate = '9'
            return orderstate, res['data']['statusDesc']


class TongjiHandler(tornado.web.RequestHandler):
    async def post(self):
        orderdate = self.get_argument("orderdate")
        # date = datetime.strptime(orderdate, "%Y%m%d")
        db = self.application.db
        coll = db.rechange

        merchantid = self.get_argument("merchantid", "")
        merchantuid = self.get_argument("merchantuid", "")
        tel_type = self.get_argument("tel_type", "")
        if merchantid:
            groups = coll.aggregate(
                [{"$match": {"merchantid": merchantid, "orderdate": orderdate, "tel_type": tel_type}}, {
                    "$group": {"_id": {"orderstate": "$orderstate", "amount": "$amount"}, "count": {"$sum": 1}}}])
            # test_range = coll.find(
            #     {"merchantid": merchantid, "orderdate": orderdate, "tel_type": tel_type})
        elif merchantuid:
            groups = coll.aggregate(
                [{"$match": {"merchantuid": merchantuid, "orderdate": orderdate, "tel_type": tel_type}}, {
                    "$group": {"_id": {"orderstate": "$orderstate", "amount": "$amount"}, "count": {"$sum": 1}}}])
        else:
            groups = coll.aggregate(
                [{"$match": {"orderdate": orderdate, "tel_type": tel_type}}, {
                    "$group": {"_id": {"orderstate": "$orderstate", "amount": "$amount"}, "count": {"$sum": 1}}}])
            # test_range = coll.find({"orderdate": orderdate, "tel_type": tel_type})
        logger.info(groups)
        # logger.info(list(groups))
        d = {}
        async for item in groups:
            orderstate = item['_id']['orderstate']
            amount = int(item['_id']['amount']) * item["count"]
            if orderstate not in d:
                d[orderstate] = {"count": item["count"], "amount": amount}
            else:
                d[orderstate]["amount"] += amount
                d[orderstate]["count"] += item["count"]
        if merchantid:
            qrcode_groups = coll.aggregate(
                [{"$match": {"merchantid": merchantid, "orderdate": orderdate, "tel_type": tel_type,
                             "orderid": {"$ne": None}}}, {
                     "$group": {"_id": {"amount": "$amount"}, "count": {"$sum": 1}}}])
            amount = 0
            count = 0
            async for item in qrcode_groups:
                amount += int(item['_id']['amount']) * item["count"]
                count += item["count"]
            d['qrcode'] = {"amount": amount, "count": count}
            self.write({merchantid: d})
        elif merchantuid:
            qrcode_groups = coll.aggregate(
                [{"$match": {"merchantuid": merchantuid, "orderdate": orderdate, "tel_type": tel_type,
                             "orderid": {"$ne": None}}}, {
                     "$group": {"_id": {"amount": "$amount"}, "count": {"$sum": 1}}}])
            amount = 0
            count = 0
            async for item in qrcode_groups:
                amount += int(item['_id']['amount']) * item["count"]
                count += item["count"]
            d['qrcode'] = {"amount": amount, "count": count}
            # self.write({merchantid: d})
            self.write({merchantuid: d})
        else:
            qrcode_groups = coll.aggregate(
                [{"$match": {"orderdate": orderdate, "tel_type": tel_type, "orderid": {"$ne": None}}}, {
                    "$group": {"_id": {"amount": "$amount"}, "count": {"$sum": 1}}}])
            amount = 0
            count = 0
            async for item in qrcode_groups:
                amount += int(item['_id']['amount']) * item["count"]
                count += item["count"]
            d['qrcode'] = {"amount": amount, "count": count}
            self.write(d)


async def aget_wxqrcode(usertel, amount, redis):
    faker = Faker(locale='zh_CN')
    ip = faker.ipv4()
    headers = {
        'User-Agent': faker.chrome(),
        "Referer": "https://shop.10086.cn/i/v1/res/numarea/13418071372?_=1559631289123",
        "Host": "shop.10086.cn"
        # 'CLIENT-IP': ip,
        # 'X-FORWARDED-FOR': ip,
    }

    proxys = await redis.smembers('un_proxy', encoding='utf-8')
    proxy = random.choice(list(proxys))
    logger.info(proxy)
    if proxy:
        conn = proxy
    else:
        conn = None
    # conn = None
    # logger.info("代理%s|%s", usertel, proxy)
    async with aiohttp.ClientSession(headers=headers) as session:
        url = 'https://shop.10086.cn/i/v1/res/numarea/%s?_=%s' % (usertel, get_ts())
        async with session.get(url, proxy=conn) as resp:
            if resp.status != 200:
                logger.error(resp.status)
                return {'retcode': '-1', 'message': '查询失败'}
            content = await resp.text(encoding='utf-8')
            prov_data = json.loads(content)
            logger.info(prov_data)
            if prov_data['retCode'] == '000000':
                prov_cd = prov_data['data']['prov_cd']
            else:
                return prov_data

        # 获取优惠
        rule_params = {'amountFlag': 1,
                       'channel': '00',
                       'enableFlag': 1, 'enableType': 0,
                       'phoneNo': base64.b64encode(usertel.encode()).decode(),
                       'provCode': prov_cd,
                       'saleFlag': 1,
                       'saleQueryType': 2}
        headers["Referer"] = url
        url = 'https://shop.10086.cn/i/v1/pay/payrule/%s' % usertel
        async with session.post(url, json=rule_params, headers=headers, proxy=conn) as resp:
            if resp.status != 200:
                logger.error(resp.status)
                return {'retcode': '-1', 'message': '查询失败'}
            rule_data = await resp.json()
            if rule_data['retCode'] != "000000":
                return rule_data
            logger.info(rule_data)
            operateId = ''
            amount = int(amount)
            pay_amount = amount
            for rule in rule_data['data']['saleRules']:
                operateId = rule['operateId']
                if '9.98' in rule['saleName']:
                    operateId = rule['operateId']
                    pay_amount = amount * 0.998
                    break
                elif '998' in rule['saleName']:
                    operateId = rule['operateId']
                    pay_amount = amount * 0.998
                    break
                elif '9.95' in rule['saleName']:
                    operateId = rule['operateId']
                    pay_amount = amount * 0.995
                    break
                elif '995' in rule['saleName']:
                    operateId = rule['operateId']
                    pay_amount = amount * 0.995
                    break
        pay_data = {'amount': pay_amount,
                    'channel': '00',
                    'chargeMoney': amount,
                    'choseMoney': amount,
                    'homeProv': prov_cd,
                    'numFlag': '0',
                    'operateId': operateId,
                    'source': ''}

        # data = {
        #     "chargeCell": usertel,
        #     "flowType": "3",
        #     "payWay": "1",
        #     "channel": "00",
        #     "_": "%d" % (time.time() * 1000),
        # }
        # headers["Referer"] = "https://shop.10086.cn/i/?f=rechargegprs&mobileNo=%s&amount=%s" % (usertel, amount)
        # url = 'https://shop.10086.cn/i/v1/pay/flow/goodslist/client'
        # async with session.get(url, params=data, headers=headers, proxy=conn) as resp:
        #
        #     rule_data = await resp.text()
        #     logger.info(rule_data)
        #     rule_data = json.loads(rule_data)
        #     rule_data = rule_data['data']['goodsList'][1]
        #     goods_id = rule_data['goodsId']
        #     goodsPrice = rule_data['cashPrice']
        #     orderPrice = goodsPrice
        #     discountId = ""
        #     productTraffic = rule_data['productTraffic']
        #     if rule_data.get('discountList'):
        #         discountCnt = rule_data['discountList'][0]['discountCnt']
        #         discountId = rule_data['discountList'][0]['marketId']
        #         orderPrice = '%.f' % (float(goodsPrice) * float(discountCnt)/100)
        # BS = AES.block_size
        # pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
        # mode = AES.MODE_CBC
        # cipher = AES.new(b'043AOQGK6ykklyZA', mode, b'043AOQGK6ykklyZA')
        # en_text = cipher.encrypt(pad(usertel).encode())
        # en_text = base64.b64encode(en_text)
        # en_text = base64.b64encode(en_text).decode()
        # logger.info(en_text)
        # pay_data = {
        #     "discountId": discountId,
        #     'channel': '00',
        #     'chargeCell': base64.b64encode(usertel.encode()).decode(),
        #     'exchangeType': '1',
        #     'goodsId': goods_id,
        #     'goodsPrice': goodsPrice,
        #     'numFlag': '0',
        #     'orderPrice': orderPrice,
        #     'productTraffic': productTraffic,
        #     'userNum': '',
        #     'userType': '2'
        # }
        url = 'https://shop.10086.cn/i/v1/pay/saveorder/%s?provinceId=%s' % (usertel, prov_cd)
        # url = 'https://shop.10086.cn/i/v1/pay/flow/submitPay/%s' % en_text
        print(url)
        headers["Host"] = "shop.10086.cn"
        headers["Origin"] = "https://shop.10086.cn"
        headers["Referer"] = "https://shop.10086.cn/i/?f=rechargegprs&mobileNo=%s&amount=%s" % (usertel, amount)
        headers["X-Requested-With"] = "XMLHttpRequest"

        async with session.post(url, json=pay_data, headers=headers, proxy=conn) as resp:
            if resp.status != 200:
                logger.error(resp.status)
                content = await resp.read()
                logger.info(content)
                return {'retcode': '-1', 'message': '查询失败'}
            pay_rsp = await resp.json()
            logger.info(pay_rsp)
            if pay_rsp['retCode'] in ("511012", "511014"):
                redis.sadd("konghao", usertel)
            return pay_rsp


class TotalHandler(PayHandler):
    async def post(self):
        exited = await self.merchant_exit()
        if not exited:
            # logger.info("商户不存在")
            self.write(json.dumps({"message": "商户不存在", "ret": -1}))
            return
        if not self.check_ip():
            self.write(json.dumps({"message": "ip错误", "ret": -1}))
            return
        if not self.check_sign():
            # logger.info("签名验证失败")
            self.write(json.dumps({"message": "签名验证失败", "ret": -1}))
            return
        db = self.application.db
        coll = db.rechange
        # test_range = coll.find({"orderstate": '2'})
        today = date.today()
        today = today.strftime('%Y%m%d')
        test_range = coll.aggregate([{"$match": {"orderstate": '2', "orderdate": today}},
                                     {"$group": {"_id": {"tel_type": "$tel_type", "amount": "$amount"},
                                                 "count": {"$sum": 1}}}])
        res = {}
        async for i in test_range:
            key = "%s_%s" % (i["_id"]["tel_type"], i["_id"]['amount'])
            res[key] = i['count']

        return_obj = self.niti_data(res, {"MERCHANTID": self.merchantid})
        return_obj.update({"ret": 0, "message": "success"})
        self.write(return_obj)


class get_upay(tornado.web.RequestHandler):
    async def get(self):
        headers = {'Host': 'upay.10010.com',
                   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0'}
        async with aiohttp.ClientSession(headers=headers) as session:
            async with session.get(
                    'http://upay.10010.com/npfwap/npfMobWap/bankcharge/index.html?version=wap&desmobile=6672070486447365') as rsp:
                logger.info(rsp.cookies)

            async with session.get(
                            'http://upay.10010.com/npfwap/NpfMob/needCode?channelType=307&_=%s' % get_ts()) as rsp:
                upay = rsp.cookies['upay_user'].value

            async with session.post('http://upay.10010.com/npfwap/NpfMob/VerifyCodeNew/getUrl',
                                    data={'channelType': 307}) as rsp:
                text = await rsp.text()
                res = json.loads(text)
                js_url = res.get("jsUrl", "")
                logger.info(upay)
                # print(js_url)
            return self.write({'upay': upay, 'js_url': js_url})


class unicom_order(tornado.web.RequestHandler):
    async def post(self):
        upay = self.get_argument("upay", "")
        ticket = self.get_argument("ticket", "")
        res = db.rechange.aggregate(
            [{'$match': {"orderdate": "20190228", "orderstate": "0", 'tel_type': 'unicom'}}, {'$sample': {'size': 1}}])
        redis = await aioredis.create_redis(address=('localhost', 6379), db=0)
        logger.info("%s|%s", upay, ticket)
        async for obj in res:
            user_tel = obj['tel_number']
            res = await get_unicom_ali(user_tel, '20', upay, redis, ticket=ticket)
            logger.info(res)
        redis.close()
        await redis.wait_closed()
        return self.write("ok")


prov_data = {
    "广东": "15916540943",
    "四川": "18781296320",
    "北京": "13810666871",
    "山东": "15898880778",
    "安徽": "15856732015",
    "重庆": "15023334327",
    "湖南": "13487584811",
    "河北": "13463146599",
    "江苏": "15262717897",
    "江西": "13979578029",
    "宁夏": "18295086757",
    "上海": "13795208292",
    "海南": "13519879406",
    "河南": "13838297354",
    "浙江": "13957913722",
    "辽宁": "15140218611",
    "湖北": "15171149844",
    "黑龙江": "18245093777",
    "福建": "15860806366",
    "云南": "13888182317",
    "吉林": "13614378225",
    "天津": "18802232221",
    "山西": "15935659388",
    "贵州": "18748707615",
    "陕西": "15109290096",
    "甘肃": "18294175311",
    "青海": "13997034150",
    "新疆": "14799831146",
    "西藏": "15889029488",
    "内蒙古": "18247683449",
    "广西": "13481107768"
}


class prov_status(tornado.web.RequestHandler):
    async def get(self, prov):
        redis = await aioredis.create_redis(address=('localhost', 6379), db=0)

        tel = prov_data[prov]
        result = await aget_wxqrcode(tel, '50', redis)
        if result["retCode"] == "000000":
            rsp = {"code": "0", "message": "交费正常"}
            # await redis.srem("unused_prov", prov)
            # if prov == '内蒙古':
            #     await redis.srem("unused_prov", "内蒙")
        else:
            rsp = {"code": "-1", "message": result.get("retMsg")}
            # await redis.sadd("unused_prov", prov)
            # if prov == '内蒙古':
            #     await redis.sadd("unused_prov", "内蒙")
        redis.close()
        await redis.wait_closed()
        return self.write(rsp)


class reg_check(tornado.web.RequestHandler):
    async def post(self):
        url = self.get_argument("url")
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
            # 'Cookie': cookies
        }

        redis = await aioredis.create_redis(address=('localhost', 6379), db=0)
        proxys = await redis.smembers('un_proxy', encoding='utf-8')
        proxy = random.choice(list(proxys))
        logger.info(proxy)
        if proxy:
            conn = proxy
        else:
            conn = None
        redis.close()
        await redis.wait_closed()
        async with aiohttp.ClientSession(headers=headers) as session:
            async with session.get(url, headers=headers, proxy=conn) as rsp:
                text = await rsp.text()
                root = lxml.html.fromstring(text)
                eles = root.xpath('/html/body/div/div[2]/div[1]//text()')
                username = root.xpath('/html/body/div/div[2]/div[2]/span')
                username = username[0].text
                if eles:
                    ele = eles[0]
                    if "激活成功" in ele:
                        async with session.get('https://shop.10086.cn/mall_200_200.html', headers=headers, proxy=conn):
                            pass
                            # session.cookie_jar.save('/app/log/cmcc_username/' + username)
                        await db.cmcc_username.update_one({'username': username}, {"$set": {"is_reg": '0'}})
                        self.write("激活成功")


class day_count(tornado.web.RequestHandler):
    async def post(self):
        merchantid = self.get_argument("merchantid", "")
        merchantuid = self.get_argument("merchantuid", "")
        start_time = self.get_argument("start_time", "")
        end_time = self.get_argument("end_time", "")
        start_time = start_time.split('-')
        end_time = end_time.split('-')
        start = datetime(*[int(i) for i in start_time])
        print(start)
        end = datetime(*[int(i) for i in end_time])
        print(end)

        db = self.application.db
        coll = db.rechange
        if merchantid:
            res = coll.aggregate([{"$match": {"merchantid": merchantid, "orderstate": '0',
                                              "time": {"$gte": start.timestamp(), "$lt": end.timestamp()}}}, {
                                      "$group": {"_id": {"orderstate": "$orderstate", "amount": "$amount",
                                                         "tel_type": "$tel_type", "merchantuid": "$merchantuid"},
                                                 "count": {"$sum": 1}}}])
        elif merchantuid:
            res = coll.aggregate([{"$match": {"merchantuid": merchantuid, "orderstate": '0',
                                              "time": {"$gte": start.timestamp(), "$lt": end.timestamp()}}}, {
                                      "$group": {"_id": {"orderstate": "$orderstate", "amount": "$amount",
                                                         "tel_type": "$tel_type", "merchantid": "$merchantid"},
                                                 "count": {"$sum": 1}}}])
        else:
            res = coll.aggregate(
                [{"$match": {"orderstate": '0', "time": {"$gte": start.timestamp(), "$lt": end.timestamp()}}}, {
                    "$group": {"_id": {"orderstate": "$orderstate", "amount": "$amount", "tel_type": "$tel_type"},
                               "count": {"$sum": 1}}}])

        d = []
        async for item in res:
            d.append(item)

        self.write(json.dumps(d))


class ctcc_fin(tornado.web.RequestHandler):
    async def get(self):
        payorderno = self.get_argument("payorderno", "")
        db = self.application.db
        coll = db.rechange
        obj = await coll.find_one({"payorderno": payorderno})
        username = obj.get("username")
        user_data = await db.cmcc_username.find_one({'username': username})
        cookies = user_data['cookies']
        redis = await aioredis.create_redis(address=('localhost', 6379), db=0)
        orderstate, message = await ctcc_query(obj['orderid'], cookies, redis)
        redis.close()
        await redis.wait_closed()
        return self.write({"orderstate": orderstate, "message": message})


class cmcc86_fin(tornado.web.RequestHandler):
    async def get(self):
        payorderno = self.get_argument("payorderno", "")
        ordernumber = self.get_argument("ordernumber", "")
        db = self.application.db
        coll = db.rechange
        if payorderno:
            obj = await coll.find_one({"payorderno": payorderno})
        else:
            obj = await coll.find_one({"ordernumber": ordernumber})
        redis = await aioredis.create_redis(address=('localhost', 6379), db=0)
        order_id = obj['orderid']

        if order_id.startswith("007"):
            orderstate, message = await cmcc_query(obj['query_url'], redis)
        else:
            username = obj['username']
            user_obj = await db.cmcc_username.find_one({"username": username})
            passwd = user_obj['passwd']
            orderdate = obj['orderdate']
            orderstate, message = await cmcc_10086_query(order_id, redis, username, passwd, orderdate)
        redis.close()
        await redis.wait_closed()
        return self.write({"orderstate": orderstate, "message": message})


class cmccft_fin(tornado.web.RequestHandler):
    async def get(self):
        payorderno = self.get_argument("payorderno", "")
        ordernumber = self.get_argument("ordernumber", "")
        db = self.application.db
        coll = db.rechange
        if payorderno:
            obj = await coll.find_one({"payorderno": payorderno})
        else:
            obj = await coll.find_one({"ordernumber": ordernumber})
        redis = await aioredis.create_redis(address=('localhost', 6379), db=0)
        # order_id = obj['orderid']
        username = obj['username']
        # user_obj = await db.cmcc_username.find_one({"username": username})
        # passwd = user_obj['passwd']
        # orderdate = obj['orderdate']
        orderstate, message = await cmcc_query(obj['query_url'], redis)
        redis.close()
        await redis.wait_closed()
        return self.write({"orderstate": orderstate, "message": message})


if __name__ == '__main__':
    client = motor.motor_tornado.MotorClient('mongodb://cs_user:cmcc5188@localhost:12018/cs_recharge')
    db = client.cs_recharge
    handlers = [
        (r"/tongji", TongjiHandler),
        (r"/pay/order_total", TotalHandler),
        (r"/get_upay", get_upay),
        (r"/get/cmcc_status/(.*)", prov_status),
        (r"/day_count", day_count),
        (r"/reg_check", reg_check),
        (r"/ctcc/result/", ctcc_fin),
        (r"/cmcc/result/", cmcc86_fin),
        (r"/unicom_order", unicom_order)
    ]
    application = tornado.web.Application(handlers, debug=False)
    application.listen(10010, address="127.0.0.1")
    loop = asyncio.get_event_loop()
    application.db = db
    # application.init_with_loop(loop)
    loop.run_forever()
